package org.example.utils;

import java.util.*;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * 链式处理列表数据的工具类
 *
 * @param <T> 列表元素类型
 */
public class Opts<T> {
    private final List<T> ts;

    /**
     * 构造方法，初始化内部列表
     *
     * @param ts 原始列表数据，若为null则使用空列表
     */
    private Opts(List<T> ts) {
        this.ts = ts == null ? Collections.emptyList() : new ArrayList<>(ts);
    }

    /**
     * 创建一个包含指定列表数据的Opts实例
     *
     * @param ts  原始列表数据
     * @param <T> 列表元素类型
     * @return 包含指定数据的Opts实例
     */
    public static <T> Opts<T> of(List<T> ts) {
        return new Opts<>(ts);
    }


    public static <T> Opts<T> ofs(T ... t) {
        if(t==null|| t.length==0){
            return empty();
        }
        return of( Arrays.stream(t).filter(Objects::nonNull).collect(Collectors.toList()));
    }

    /**
     * 创建一个空的Opts实例
     *
     * @param <T> 列表元素类型
     * @return 空的Opts实例
     */
    public static <T> Opts<T> empty() {
        return new Opts<>(Collections.emptyList());
    }

    /**
     * 执行自定义转换函数，将当前列表转换为新的列表
     *
     * @param func  转换函数，接收当前列表并返回新列表
     * @param <V>   新列表元素类型
     * @return 转换后的新Opts实例，如果当前列表为空则返回空实例
     */
    public <V> Opts<V> exec(Function<List<T>, List<V>> func) {
        return isPresent() ? Opts.of(func.apply(ts)) : Opts.empty();
    }

    /**
     * 根据条件过滤列表中的元素
     *
     * @param predicate 过滤条件
     * @return 包含符合条件元素的新Opts实例，如果当前列表为空则返回当前实例
     */
    public Opts<T> filter(Predicate<T> predicate) {
        return isPresent()
                ? Opts.of(ts.stream().filter(predicate).collect(Collectors.toList()))
                : this;
    }

    /**
     * 将列表中的每个元素映射为新的元素
     *
     * @param mapper  映射函数，将每个元素转换为新元素
     * @param <R>     新元素类型
     * @return 映射后的新Opts实例，如果当前列表为空则返回空实例
     */
    public <R> Opts<R> map(Function<T, R> mapper) {
        return isPresent()
                ? Opts.of(ts.stream().map(mapper).collect(Collectors.toList()))
                : Opts.empty();
    }

    /**
     * 判断当前列表是否非空
     *
     * @return 如果列表非空返回true，否则返回false
     */
    public boolean isPresent() {
        return !ts.isEmpty();
    }

    /**
     * 获取当前列表的副本
     *
     * @return 当前列表的副本
     */
    public List<T> get() {
        return isPresent()?ts:new ArrayList<>();
    }

    /**
     * 将列表转换为Map，使用元素的某个属性作为键，元素本身作为值
     *
     * @param keyFunction 生成键的函数
     * @param <K>         键类型
     * @return 转换后的Map
     */
    public <K> Map<K, T> toMap(Function<T, K> keyFunction) {
        return toMap(keyFunction, Function.identity());
    }

    /**
     * 将列表转换为Map，使用指定的键和值生成函数
     *
     * @param keyMapper   生成键的函数
     * @param valueMapper 生成值的函数
     * @param <K>         键类型
     * @param <V>         值类型
     * @return 转换后的Map，如果当前列表为空则返回空Map
     */
    public <K, V> Map<K, V> toMap(
            Function<T, K> keyMapper,
            Function<T, V> valueMapper
    ) {
        if (!isPresent()) return Collections.emptyMap();
        return ts.stream()
                .filter(Objects::nonNull)
                .filter(t -> keyMapper.apply(t) != null)
                .collect(Collectors.toMap(
                        keyMapper,
                        valueMapper,
                        (existing, replacement) -> existing
                ));
    }

    /**
     * 获取列表中的第一个元素
     *
     * @return 第一个元素的Optional包装，如果列表为空则返回空Optional
     */
    public Optional<T> first() {
        return isPresent()? ts.stream().findFirst(): Optional.empty();
    }

    /**
     * 获取列表中元素的数量
     *
     * @return 元素数量
     */
    public long count() {
        return ts.size();
    }

    /**
     * 对列表中的每个元素执行指定操作
     *
     * @param action 要执行的操作
     */
    public void forEach(Consumer<T> action) {
        ts.forEach(action);
    }

    public Opt<T> one() {
        return isPresent()?Opt.of(ts.get(0)):Opt.of(null);
    }

    public Opts<T> action(Consumer<List<T>> consumer) {
        if(isPresent()){
            consumer.accept(ts);
        }
        return this;
    }
}
